package com.honkentuber;

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.simple.JSONObject;

import com.google.appengine.api.datastore.KeyFactory;


public abstract class Servlet extends HttpServlet {
  private static final long serialVersionUID = -7488641862467533095L;

  protected static final Logger LOG = Logger.getLogger(Servlet.class
      .getName());

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    doIt(req, resp);
  }

  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    doIt(req, resp);
  }

  @SuppressWarnings("unchecked")
  private void doIt(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    AppContext ctx = newAppContext(req, resp);
    try {
      if ("1".equals(req.getParameter("html"))) {
        String jspResponse = newJspResponse(ctx);
        req.setAttribute("loginUrl", ctx.loginUrl);
        req.setAttribute("logoutUrl", ctx.logoutUrl);
        if (ctx.user != null) {
          req.setAttribute("userKey", ctx.user.getKey());
        }
        req.setAttribute("userCache", ctx.db.getUserCache());
        req.getRequestDispatcher(jspResponse).forward(req, resp);
      } else {
        JSONObject json = newJsonResponse(ctx);
        if (ctx.user != null) {
          json.put("userKey", KeyFactory.keyToString(ctx.user.getKey()));
        }
        json.put("userCache", ctx.db.getUserCache().toJson());
        req.setAttribute("json", json.toJSONString());
        req.getRequestDispatcher("json.jsp").forward(req, resp);
      }
    } catch (IOException ex) {
      LOG.log(Level.SEVERE, "servlet error", ex);
      throw ex;
    } catch (Exception ex) {
      LOG.log(Level.SEVERE, "servlet error", ex);
    } finally {
      ctx.persistenceManager.close();
    }

    ctx.timingLogger.recordTiming("end");
    LOG.info(ctx.timingLogger.getTimingString());
  }

  protected AppContext newAppContext(HttpServletRequest req,
      HttpServletResponse resp) {
    return new AppContext(req, resp);
  }

  /**
   * @param ctx Context.
   * @return JSP path.
   */
  protected abstract String newJspResponse(AppContext ctx);

  /**
   * @param ctx Context.
   * @return JSON response object.
   */
  protected abstract JSONObject newJsonResponse(AppContext ctx);
}